using System;
using OpenRay;
using NUnit.Framework;

using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Security.Cryptography;
using System.Diagnostics;

namespace Tests
{
	[TestFixture]
	public class TestFramebuffer
	{
		private void SavePNG( FrameBuffer fb, string s ) {
			Bitmap bmp = new Bitmap(fb.Width, fb.Height );
			
			for ( int y = 0; y < fb.Height; y++ )
			{
				for ( int x = 0; x < fb.Width; x++ )
				{
					float[] color = fb.GetArgb(x,y);
					bmp.SetPixel(x, y, System.Drawing.Color.FromArgb( (int)(color[0] * 255f), (int)(color[1] * 255f), (int)(color[2] * 255f), (int)(color[3] * 255f) ) );
				}
			}
			
			bmp.Save(s, ImageFormat.Png );
			bmp.Dispose();
		}
		
		private string ComputeMD5( FrameBuffer fb ) {
			int length = fb.Width * fb.Height * 4 * 4;
			
			byte[] bytes = new byte[length];
			
			for( int i = 0, x = 0; i < fb.Height; i++ ) 
			{
				for ( int j = 0; j < fb.Width; j++ )
				{
					float[] pixel = fb.GetArgb(j, i);
					Debug.Assert( pixel.Length == 4 );
					foreach ( float f in pixel )
					{
						byte[] t = BitConverter.GetBytes(f);
						Debug.Assert( t.Length == 4 );
						foreach ( byte b in t )
						{
							bytes[x++] = b;
						}
					}
				}
			}
			
			MD5 md5 = new MD5CryptoServiceProvider();
			byte[] retVal = md5.ComputeHash(bytes);
			
			StringBuilder sb = new StringBuilder();
			
			for ( int i = 0; i < retVal.Length; i++ )
			{
				sb.Append(retVal[i].ToString("x2"));
			}
			
			return sb.ToString();
		}
		
		[Test]
		public void TestResize ()
		{
			FrameBuffer fb = new FrameBuffer(100, 100);
			fb.Resize(200, 200);
			
			Assert.AreEqual( 200, fb.Width );
			Assert.AreEqual( 200, fb.Height );
		}
		
		[Test]
		public void TestFill ()
		{
			FrameBuffer fb = new FrameBuffer(100, 100);
			OpenRay.Color c = new OpenRay.Color( 1f, 0f, 1f, 1f );
				
			fb.FillArgb( c.ToArgb() );
			
			string s = ComputeMD5( fb );
			string result = "cac1b586a28119e4c451412b482ea017";
			
			if ( !s.Equals(result) )
			{
				SavePNG(fb, "TestFill.png");
				Assert.AreEqual(result, s);
			}
		}
		
		[Test]
		public void TestSet ()
		{
			const int tileSize = 10;
			
			FrameBuffer fb = new FrameBuffer(100, 100);
			OpenRay.Color white = new OpenRay.Color( 1f, 1f, 1f, 1f );
			OpenRay.Color black = new OpenRay.Color( 0f, 0f, 0f, 1f );
				
			for ( int i = 0; i < fb.Height; i++ )
			{
				for ( int j = 0; j < fb.Width; j++ )
				{
					if ( ( i / tileSize + j / tileSize ) % 2 == 1 )
						fb.SetPixelArgb(j, i, white.ToArgb() );
					else
						fb.SetPixelArgb(j, i, black.ToArgb() );
				}
			}
			
			string s = ComputeMD5( fb );
			string result = "7e47cc9f1810ba9eaafdc7f7a6be2b77";
			
			if ( !s.Equals(result) )
			{
				SavePNG(fb, "TestSet.png");
				Assert.AreEqual(result, s);
			}
		}
	}
}

